import { BadRequestException, Injectable, NotFoundException } from '@nestjs/common'
import { InjectRepository } from '@nestjs/typeorm'
import { Repository } from 'typeorm'
import { format } from 'date-fns'
import { CreateMainPlanDto, MainPlanItemDto } from './dto/create-main-plan.dto'
import { UpdateMainPlanDto } from './dto/update-main-plan.dto'
import { MainPlanEntity } from './main-plan.entity'
import { SubPlanEntity } from '../sub-plan/sub-plan.entity'
import { ClassEntity } from '~/modules/admin/manage/class/entities/class.entity'
import { StudentClassEntity } from '~/modules/admin/manage/student/entities/student-class.entity'
import { StudentEntity } from '~/modules/admin/manage/student/entities/student.entity'
import { StudentCreateMainPlanDto, StudentMainPlanItemDto } from './dto/student-create-main-plan.dto'

@Injectable()
export class MainPlanService {
  constructor(
    @InjectRepository(MainPlanEntity)
    private readonly mainPlanRepository: Repository<MainPlanEntity>,
    @InjectRepository(SubPlanEntity)
    private readonly subPlanRepository: Repository<SubPlanEntity>,
    @InjectRepository(ClassEntity)
    private readonly classRepository: Repository<ClassEntity>,
    @InjectRepository(StudentClassEntity)
    private readonly studentClassRepository: Repository<StudentClassEntity>,
    @InjectRepository(StudentEntity)
    private readonly studentRepository: Repository<StudentEntity>,
  ) {}

  // 生成主计划ID
  private async generatePlanId(): Promise<string> {
    const date = new Date()
    const dateStr = format(date, 'yyyyMMdd')
    const prefix = `PL${dateStr}`
    
    // 查询当天最大ID
    const latestPlan = await this.mainPlanRepository
      .createQueryBuilder('plan')
      .where('plan.planId LIKE :prefix', { prefix: `${prefix}%` })
      .orderBy('plan.planId', 'DESC')
      .getOne()
    
    let sequence = 1
    if (latestPlan) {
      const latestSequence = parseInt(latestPlan.planId.substring(10), 10) || 0
      sequence = latestSequence + 1
    }
    
    return `${prefix}${sequence.toString().padStart(3, '0')}`
  }
  
  // 生成子计划ID
  private async generateSubPlanId(): Promise<string> {
    const date = new Date()
    const dateStr = format(date, 'yyyyMMdd')
    const prefix = `SPL${dateStr}`
    
    // 查询当天最大ID
    const latestPlan = await this.subPlanRepository
      .createQueryBuilder('plan')
      .where('plan.subPlanId LIKE :prefix', { prefix: `${prefix}%` })
      .orderBy('plan.subPlanId', 'DESC')
      .getOne()
    
    let sequence = 1
    if (latestPlan) {
      const latestSequence = parseInt(latestPlan.subPlanId.substring(11), 10) || 0
      sequence = latestSequence + 1
    }
    
    return `${prefix}${sequence.toString().padStart(3, '0')}`
  }

  // 根据班级ID获取班级开班时间
  private async getClassStartTime(classId: string): Promise<Date | null> {
    const classEntity = await this.classRepository.findOne({
      where: { classId }
    })
    
    if (!classEntity) {
      throw new NotFoundException(`班级ID ${classId} 不存在`)
    }
    
    return classEntity.startAt || null
  }

  // 批量创建主计划
  async create(createMainPlanDto: CreateMainPlanDto, userId: number) {
    const { plans } = createMainPlanDto
    
    if (!plans || plans.length === 0) {
      throw new BadRequestException('请提供至少一个计划信息')
    }
    
    const results = []
    
    for (const planItem of plans) {
      const result = await this.createSinglePlan(planItem, userId)
      results.push(result)
    }
    
    return results
  }
  
  // 创建单个主计划及其子计划
  private async createSinglePlan(planItem: MainPlanItemDto, userId: number) {
    const { classId, planName, subPlans, punchStartAt, mark } = planItem
    
    // 校验班级是否存在
    const classEntity = await this.classRepository.findOne({
      where: { classId }
    })
    
    if (!classEntity) {
      throw new NotFoundException(`班级ID ${classId} 不存在`)
    }
    
    // 获取打卡开始时间
    let startTime: Date | null = null
    if (punchStartAt) {
      startTime = new Date(punchStartAt)
    } else {
      startTime = classEntity.startAt || new Date()
    }
    
    // 生成主计划ID
    const planId = await this.generatePlanId()
    
    // 创建主计划
    const mainPlan = this.mainPlanRepository.create({
      planId,
      planName,
      classId,
      mark: mark || '',
      progress: 0,
      punchStartAt: startTime,
      publishAt: new Date(),
      createBy: userId,
      updateBy: userId
    })
    
    const savedMainPlan = await this.mainPlanRepository.save(mainPlan)
    
    // 解析子计划列表
    const subPlanNames = subPlans.split('-').filter(name => name.trim() !== '')
    
    // 创建子计划
    const subPlanEntities: SubPlanEntity[] = []
    
    for (const subPlanName of subPlanNames) {
      const subPlanId = await this.generateSubPlanId()
      
      const subPlan = this.subPlanRepository.create({
        planId: savedMainPlan.id,
        subPlanId,
        subPlanName: subPlanName.trim(),
        subPlanMark: '',
        createBy: userId,
        updateBy: userId
      })
      
      const savedSubPlan = await this.subPlanRepository.save(subPlan)
      subPlanEntities.push(savedSubPlan)
    }
    
    return {
      ...savedMainPlan,
      subPlans: subPlanEntities
    }
  }
  
  // 复制主计划
  async copy(createMainPlanDto: CreateMainPlanDto, userId: number) {
    return this.create(createMainPlanDto, userId)
  }

  // 计算主计划进度
  private async calculateProgress(mainPlanId: number): Promise<number> {
    try {
      // 获取主计划
      const mainPlan = await this.mainPlanRepository.findOne({
        where: { id: mainPlanId, isDelete: 0 }
      });
      
      if (!mainPlan) {
        return 0;
      }

      // 检查是否为学生创建的主计划（classId以"STU"开头）
      if (mainPlan.classId.startsWith('STU')) {
        // 从classId提取学生ID
        const studentIdStr = mainPlan.classId.substring(3);
        let studentId: number;
        
        try {
          studentId = parseInt(studentIdStr, 10);
          
          // 添加数字有效性检查
          if (isNaN(studentId)) {
            console.error(`无效的学生ID: ${studentIdStr}`);
            return 0;
          }
          
          // 获取学生信息
          const student = await this.studentRepository.findOne({
            where: { id: studentId, isDelete: 0 }
          });
          
          if (!student) {
            console.error(`未找到学生ID ${studentId}`);
            return 0;
          }
          
          // 获取所有未删除的子计划
          const subPlans = await this.subPlanRepository.find({
            where: { planId: mainPlanId, isDelete: 0 }
          });
          
          if (!subPlans || subPlans.length === 0) {
            console.log(`主计划 ${mainPlanId} 没有子计划`);
            return 0;
          }
          
          // 对于学生计划，我们假设每个子计划需要打卡一次
          // 查询学生的所有打卡记录
          const studentClassRecords = await this.studentClassRepository.find({
            where: { studentId, isDelete: 0 }
          });
          
          if (!studentClassRecords || studentClassRecords.length === 0) {
            console.log(`学生 ${studentId} 没有打卡记录`);
            return 0;
          }
          
          // 计算总打卡天数
          const totalCheckinDays = studentClassRecords.reduce((sum, record) => sum + (record.checkinDays || 0), 0);
          
          // 计算子计划的总数
          const totalSubPlans = subPlans.length;
          
          // 计算进度百分比 (每个子计划一天 * 进度上限设为100%)
          const progress = Math.min(100, (totalCheckinDays / totalSubPlans) * 100);
          
          console.log(`学生计划 ${mainPlanId} 进度计算: 学生ID=${studentId}, 子计划数=${totalSubPlans}, 总打卡天数=${totalCheckinDays}, 进度=${progress.toFixed(2)}%`);
          
          // 更新主计划进度
          await this.mainPlanRepository.update(mainPlanId, { progress });
          
          // 如果进度达到100%，设置完成时间
          if (progress >= 100 && !mainPlan.completeAt) {
            await this.mainPlanRepository.update(mainPlanId, { completeAt: new Date() });
          }
          
          return progress;
        } catch (error) {
          console.error(`解析学生计划ID失败: ${error.message}`);
          return 0;
        }
      }
      
      // 以下是原有的班级主计划进度计算逻辑
      // 获取班级信息
      const classEntity = await this.classRepository.findOne({
        where: { classId: mainPlan.classId }
      });
      
      if (!classEntity) {
        console.error(`未找到班级: ${mainPlan.classId}`);
        return 0;
      }
      
      // 获取班级中的所有学生
      const studentClassRecords = await this.studentClassRepository.find({
        where: { classId: classEntity.id, isDelete: 0 }
      });
      
      if (!studentClassRecords || studentClassRecords.length === 0) {
        console.log(`班级 ${mainPlan.classId} 没有学生`);
        return 0;
      }
      
      // 获取所有未删除的子计划
      const subPlans = await this.subPlanRepository.find({
        where: { planId: mainPlanId, isDelete: 0 }
      });
      
      if (!subPlans || subPlans.length === 0) {
        console.log(`主计划 ${mainPlanId} 没有子计划`);
        return 0;
      }
      
      // 计算理论总打卡次数 = 学生数 * 子计划数
      const totalStudents = studentClassRecords.length;
      const totalSubPlans = subPlans.length;
      const theoreticalTotalCheckins = totalStudents * totalSubPlans;
      
      if (theoreticalTotalCheckins === 0) {
        return 0;
      }
      
      // 计算实际打卡总次数
      const actualTotalCheckins = studentClassRecords.reduce((sum, record) => sum + (record.checkinDays || 0), 0);
      
      // 计算进度百分比
      const progress = Math.min(100, (actualTotalCheckins / theoreticalTotalCheckins) * 100);
      
      console.log(`主计划 ${mainPlanId} 进度计算: 学生数=${totalStudents}, 子计划数=${totalSubPlans}, 理论打卡总数=${theoreticalTotalCheckins}, 实际打卡总数=${actualTotalCheckins}, 进度=${progress.toFixed(2)}%`);
      
      // 更新主计划进度
      await this.mainPlanRepository.update(mainPlanId, { progress });
      
      // 如果进度达到100%，设置完成时间
      if (progress >= 100 && !mainPlan.completeAt) {
        await this.mainPlanRepository.update(mainPlanId, { completeAt: new Date() });
      }
      
      return progress;
    } catch (error) {
      console.error(`计算主计划进度失败: ${error.message}`);
      return 0;
    }
  }

  // 查询所有主计划
  async findAll() {
    const mainPlans = await this.mainPlanRepository.find({
      where: { isDelete: 0 },
      order: { createdAt: 'DESC' }
    })
    
    const results = []
    
    for (const mainPlan of mainPlans) {
      // 计算并更新进度
      await this.calculateProgress(mainPlan.id);
      
      // 重新获取更新后的主计划
      const updatedMainPlan = await this.mainPlanRepository.findOne({
        where: { id: mainPlan.id }
      });
      
      // 查询子计划
      const subPlans = await this.subPlanRepository.find({
        where: { planId: mainPlan.id, isDelete: 0 }
      })
      
      // 检查是否为学生创建的主计划
      let className = '';
      let effectivePunchEndAt: Date | null = null;
      let studentName: string | null = null;
      
      if (mainPlan.classId.startsWith('STU')) {
        // 从classId提取学生ID
        const studentIdStr = mainPlan.classId.substring(3);
        
        try {
          const studentId = parseInt(studentIdStr, 10);
          
          // 添加数字有效性检查
          if (!isNaN(studentId)) {
            // 查询学生信息
            const student = await this.studentRepository.findOne({
              where: { id: studentId, isDelete: 0 }
            });
            
            if (student) {
              // 使用学生姓名作为className，便于前端显示
              className = `${student.userName}的个人计划`;
              studentName = student.userName;
              effectivePunchEndAt = student.expireAt; // 使用学生过期时间
            }
          } else {
            // 处理无效ID情况
            console.log(`无效的学生ID数字: ${studentIdStr}`);
            className = '个人计划';  // 设置默认名称
          }
        } catch (error) {
          console.error(`解析学生计划ID失败: ${error.message}`);
          className = '个人计划';  // 设置默认名称
        }
      } else {
        // 常规班级主计划，查询班级信息
        try {
          const classEntity = await this.classRepository.findOne({
            where: { classId: mainPlan.classId }
          })
          
          if (classEntity) {
            className = classEntity.className;
            effectivePunchEndAt = classEntity.expireAt;
          }
        } catch (error) {
          console.error(`获取班级信息失败: ${error.message}`);
        }
      }
      
      results.push({
        ...updatedMainPlan,
        className,
        effectivePunchEndAt,
        studentName, // 添加学生姓名字段
        subPlans
      })
    }
    
    return results
  }

  // 查询单个主计划
  async findOne(id: number) {
    const mainPlan = await this.mainPlanRepository.findOne({
      where: { id, isDelete: 0 }
    })
    
    if (!mainPlan) {
      throw new NotFoundException(`主计划ID ${id} 不存在`)
    }
    
    // 计算并更新进度
    await this.calculateProgress(id);
    
    // 重新获取更新后的主计划
    const updatedMainPlan = await this.mainPlanRepository.findOne({
      where: { id }
    });
    
    // 查询子计划
    const subPlans = await this.subPlanRepository.find({
      where: { planId: id, isDelete: 0 }
    })
    
    // 检查是否为学生创建的主计划
    let className = '';
    let effectivePunchEndAt: Date | null = null;
    let studentName: string | null = null;
    
    if (mainPlan.classId.startsWith('STU')) {
      // 从classId提取学生ID
      const studentIdStr = mainPlan.classId.substring(3);
      
      try {
        const studentId = parseInt(studentIdStr, 10);
        
        // 添加数字有效性检查
        if (!isNaN(studentId)) {
          // 查询学生信息
          const student = await this.studentRepository.findOne({
            where: { id: studentId, isDelete: 0 }
          });
          
          if (student) {
            // 使用学生姓名作为className，便于前端显示
            className = `${student.userName}的个人计划`;
            studentName = student.userName;
            effectivePunchEndAt = student.expireAt; // 使用学生过期时间
          }
        } else {
          // 处理无效ID情况
          console.log(`无效的学生ID数字: ${studentIdStr}`);
          className = '个人计划';  // 设置默认名称
        }
      } catch (error) {
        console.error(`解析学生计划ID失败: ${error.message}`);
        className = '个人计划';  // 设置默认名称
      }
    } else {
      // 常规班级主计划，查询班级信息
      try {
        const classEntity = await this.classRepository.findOne({
          where: { classId: mainPlan.classId }
        })
        
        if (classEntity) {
          className = classEntity.className;
          effectivePunchEndAt = classEntity.expireAt;
        }
      } catch (error) {
        console.error(`获取班级信息失败: ${error.message}`);
      }
    }
    
    return {
      ...updatedMainPlan,
      className,
      effectivePunchEndAt,
      studentName, // 添加学生姓名字段
      subPlans
    }
  }

  // 更新主计划
  async update(id: number, updateMainPlanDto: UpdateMainPlanDto, userId: number) {
    const mainPlan = await this.mainPlanRepository.findOne({
      where: { id, isDelete: 0 }
    })
    
    if (!mainPlan) {
      throw new NotFoundException(`主计划ID ${id} 不存在`)
    }
    
    // 更新字段
    Object.assign(mainPlan, {
      ...updateMainPlanDto,
      updateBy: userId
    });
    
    // 保存更新
    await this.mainPlanRepository.save(mainPlan);
    
    return `主计划 ${id} 更新成功`
  }

  // 删除主计划
  async remove(id: number) {
    const mainPlan = await this.mainPlanRepository.findOne({
      where: { id, isDelete: 0 }
    })
    
    if (!mainPlan) {
      throw new NotFoundException(`主计划ID ${id} 不存在`)
    }
    
    // 标记删除主计划
    await this.mainPlanRepository.update(id, { isDelete: 1 })
    
    // 标记删除关联的子计划
    await this.subPlanRepository.update(
      { planId: id, isDelete: 0 },
      { isDelete: 1 }
    )
    
    return `主计划 ${id} 删除成功`
  }

  /**
   * 学生打卡学习计划
   * @param id 主计划ID
   * @param studentId 学生ID
   * @param userId 操作用户ID
   * @returns 打卡结果
   */
  async checkinMainPlan(id: number, studentId: number, userId: number) {
    // 1. 查找主计划
    const mainPlan = await this.mainPlanRepository.findOne({
      where: { id, isDelete: 0 }
    });

    if (!mainPlan) {
      throw new NotFoundException(`主计划ID ${id} 不存在`);
    }

    // 2. 检查学生是否存在
    const student = await this.studentRepository.findOne({
      where: { id: studentId, isDelete: 0 }
    });

    if (!student) {
      throw new NotFoundException(`学生ID ${studentId} 不存在`);
    }

    // 3. 获取班级实体
    const classEntity = await this.classRepository.findOne({
      where: { classId: mainPlan.classId }
    });

    if (!classEntity) {
      throw new NotFoundException(`班级ID ${mainPlan.classId} 不存在`);
    }

    // 4. 检查学生是否在班级中
    const studentClass = await this.studentClassRepository.findOne({
      where: { studentId, classId: classEntity.id, isDelete: 0 }
    });

    if (!studentClass) {
      throw new BadRequestException(`学生ID ${studentId} 不在班级ID ${mainPlan.classId} 中`);
    }

    // 5. 检查今天是否已经打卡
    const today = new Date();
    today.setHours(0, 0, 0, 0);
    
    if (studentClass.lastCheckinAt) {
      const lastCheckin = new Date(studentClass.lastCheckinAt);
      lastCheckin.setHours(0, 0, 0, 0);
      
      if (lastCheckin.getTime() === today.getTime()) {
        return { 
          message: '今天已经打卡', 
          checkinDays: studentClass.checkinDays,
          mainPlanProgress: mainPlan.progress
        };
      }
    }

    // 6. 更新打卡信息
    studentClass.checkinDays += 1;
    studentClass.lastCheckinAt = new Date();
    
    await this.studentClassRepository.save(studentClass);

    // 7. 更新主计划进度
    await this.calculateProgress(id);
    
    // 8. 重新获取更新后的主计划
    const updatedMainPlan = await this.mainPlanRepository.findOne({
      where: { id }
    });
    
    return { 
      message: '打卡成功', 
      checkinDays: studentClass.checkinDays,
      mainPlanProgress: updatedMainPlan.progress
    };
  }

  /**
   * 学生创建主计划
   * @param studentCreateMainPlanDto 学生创建主计划DTO
   * @param userId 操作用户ID
   * @returns 创建的主计划列表
   */
  async studentCreateMainPlan(studentCreateMainPlanDto: StudentCreateMainPlanDto, userId: number) {
    const { studentId, plans } = studentCreateMainPlanDto;
    
    if (!plans || plans.length === 0) {
      throw new BadRequestException('请提供至少一个计划信息');
    }
    
    // 1. 查找学生信息
    const student = await this.studentRepository.findOne({
      where: { id: studentId, isDelete: 0 }
    });
    
    if (!student) {
      throw new NotFoundException(`学生ID ${studentId} 不存在`);
    }
    
    // 2. 创建主计划列表
    const results = [];
    
    for (const planItem of plans) {
      const result = await this.createStudentPlan(studentId, planItem, userId);
      results.push(result);
    }
    
    return results;
  }
  
  /**
   * 创建单个学生主计划
   * @param studentId 学生ID
   * @param planItem 主计划项
   * @param userId 操作用户ID
   * @returns 创建的主计划
   */
  private async createStudentPlan(studentId: number, planItem: StudentMainPlanItemDto, userId: number) {
    const { planName, subPlans, punchStartAt, mark } = planItem;
    
    // 获取学生信息
    const student = await this.studentRepository.findOne({
      where: { id: studentId }
    });
    
    // 1. 设置打卡开始时间
    let startTime: Date | null = null;
    if (punchStartAt) {
      startTime = new Date(punchStartAt);
    } else {
      // 默认使用当前时间
      startTime = new Date();
    }
    
    // 2. 生成主计划ID
    const planId = await this.generatePlanId();
    
    // 3. 创建主计划 - 使用特殊的学生专属班级ID格式
    const studentClassId = `STU${studentId}`;
    
    const mainPlan = this.mainPlanRepository.create({
      planId,
      planName,
      classId: studentClassId, // 使用特殊格式的ID标识这是学生计划
      mark: mark || '',
      progress: 0,
      punchStartAt: startTime,
      publishAt: new Date(),
      createBy: userId,
      updateBy: userId
    });
    
    const savedMainPlan = await this.mainPlanRepository.save(mainPlan);
    
    // 4. 解析子计划列表
    const subPlanNames = subPlans.split('-').filter(name => name.trim() !== '');
    
    // 5. 创建子计划
    const subPlanEntities: SubPlanEntity[] = [];
    
    for (const subPlanName of subPlanNames) {
      const subPlanId = await this.generateSubPlanId();
      
      const subPlan = this.subPlanRepository.create({
        planId: savedMainPlan.id,
        subPlanId,
        subPlanName: subPlanName.trim(),
        subPlanMark: '',
        createBy: userId,
        updateBy: userId
      });
      
      const savedSubPlan = await this.subPlanRepository.save(subPlan);
      subPlanEntities.push(savedSubPlan);
    }
    
    return {
      ...savedMainPlan,
      studentId, // 添加学生ID到返回结果中
      subPlans: subPlanEntities
    };
  }
}
